<template>
    <el-container :height="containerHeight">
        <el-aside style="padding: 10px 0px 0px 0px;background: #fff;border-right: 1px solid #dfe6ec;width: 220px;">
            <el-tree style="font-size: 14px;" ref="leftTree" :data="deptList" node-key="id" :props="defaultProps"
                default-expand-all empty-text="暂无数据" :show-checkbox="false" :highlight-current="false"
                :expand-on-click-node="false" @node-click="handleNodeClick">
                <div class="customer-tree-node" slot-scope="{ node, data }">
                    <span v-if="data.children.length === 0">
                        <i class="el-icon-document"></i>
                    </span>
                    <span v-else @click.stop="changeIcon(data)">
                        <svg-icon v-if="data.open" icon-class="add-s"></svg-icon>
                        <svg-icon v-else icon-class="sub-s"></svg-icon>
                    </span>
                    <span style="margin-left: 3px;">{{ node.label }}</span>
                </div>
            </el-tree>
        </el-aside>

        <el-main>
            <el-form :model="searchModel" ref="searchForm" label-width="80px" :inline="true" size="small">
                <el-form-item>
                    <el-input v-model="searchModel.username" placeholder="请输入用户名"></el-input>
                </el-form-item>
                <el-form-item>
                    <el-input v-model="searchModel.realName" placeholder="请输入真实姓名"></el-input>
                </el-form-item>
                <el-form-item>
                    <el-input v-model="searchModel.phone" placeholder="请输入电话号码"></el-input>
                </el-form-item>
                <el-form-item>
                    <el-button icon="el-icon-search" type="primary"
                        @click="search(departmentId, pageNo, pageSize)">查找</el-button>
                    <el-button icon="el-icon-refresh-right" @click="resetValue">重置</el-button>
                    <el-button icon="el-icon-plus" size="small" type="success" @click="openAddWindow()" v-if="$hasPermission('sys:user:add')">新增</el-button>
                </el-form-item>
            </el-form>

            <el-table :height="tableHeight" :data="userList" border stripe style="width: 100%;margin-bottom: 10px;">
                <el-table-column prop="username" label="用户名"></el-table-column>
                <el-table-column prop="realName" label="姓名"></el-table-column>
                <el-table-column prop="departmentName" label="所属部门"></el-table-column>
                <el-table-column prop="phone" label="电话号码"></el-table-column>
                <el-table-column prop="email" label="邮箱地址"></el-table-column>
                <el-table-column align="center" width="290" label="操作">
                    <template slot-scope="scope">
                        <el-button icon="el-icon-edit" type="primary" size="mini"
                            @click="handleEdit(scope.row)" v-if="$hasPermission('sys:user:edit')">编辑</el-button>
                        <el-button icon="el-icon-delete" type="danger" size="mini" 
                            @click="handleDelete(scope.row)" v-if="$hasPermission('sys:user:delete')">删除</el-button>
                        <el-button icon="el-icon-setting" type="primary" size="mini"
                            @click="assignRole(scope.row)" v-if="$hasPermission('sys:user:assign')">分配角色</el-button>
                    </template>
                </el-table-column>
            </el-table>

            <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange"
                :current-page="pageNo" :page-sizes="[10, 20, 30, 40, 50]" :page-size="10"
                layout="total, sizes, prev, pager, next, jumper" :total="total">

            </el-pagination>

            <system-dialog :title="userDialog.title" :width="userDialog.width" :height="userDialog.height"
                :visible="userDialog.visible" @onClose="onClose" @onConfirm="onConfirm">
                <div slot="content">
                    <el-form :model="user" ref="userForm" :rules="rules" label-width="80px" :inline="true" size="small">
                        <el-form-item prop="username" label="用户名">
                            <el-input v-model="user.username"></el-input>
                        </el-form-item>
                        <el-form-item prop="password" v-if="user.id === ''" label="密码">
                            <el-input type="password" v-model="user.password"></el-input>
                        </el-form-item>
                        <el-form-item prop="departmentName" label="所属部门">
                            <el-input v-model="user.departmentName" :readonly="true"
                                @click.native="selectDepartment"></el-input>
                        </el-form-item>
                        <el-form-item prop="realName" label="姓名">
                            <el-input v-model="user.realName"></el-input>
                        </el-form-item>
                        <el-form-item prop="phone" label="电话">
                            <el-input v-model="user.phone"></el-input>
                        </el-form-item>
                        <el-form-item prop="email" label="邮箱地址">
                            <el-input v-model="user.email"></el-input>
                        </el-form-item>
                        <el-form-item prop="gender" label="性别">
                            <el-radio-group v-model="user.gender">
                                <el-radio :label="0">男</el-radio>
                                <el-radio :label="1">女</el-radio>
                            </el-radio-group>
                        </el-form-item>

                        <br>
                        <el-form-item label="头像">
                            <el-upload :show-file-list="false" :on-success="handleAvatarSuccess"
                                :before-upload="beforeAvatarUpload" class="avatar-uploader" :headers="uploadHeader"
                                :action="`http://localhost:8080/api/qiniu/file/upload?module=avatar&avatar=${this.user.avatar}`">
                                <img class="avatar" v-if="user.avatar" :src="user.avatar">
                                <i v-else class="el-icon-plus avatar-uploader-icon"></i>
                            </el-upload>
                        </el-form-item>
                    </el-form>
                </div>
            </system-dialog>

            <system-dialog :title="parentDialog.title" :width="parentDialog.width" :height="parentDialog.height"
                :visible="parentDialog.visible" @onClose="onParentClose" @onConfirm="onParentConfirm">
                <div slot="content">
                    <el-tree ref="parentTree" :data="parentList" node-key="id" :props="defaultProps" default-expand-all
                        empty-text="暂无数据" :show-checkbox="false" :highlight-current="false" :expand-on-click-node="false"
                        @node-click="parentClick">
                        <div class="customer-tree-node" slot-scope="{ node, data }">
                            <span v-if="data.children.length === 0">
                                <i class="el-icon-document"></i>
                            </span>
                            <span v-else @click.stop="changeParentIcon(data)">
                                <svg-icon v-if="data.open" icon-class="add-s"></svg-icon>
                                <svg-icon v-else icon-class="sub-s"></svg-icon>
                            </span>
                            <span style="margin-left: 3px;">{{ node.label }}</span>
                        </div>
                    </el-tree>
                </div>
            </system-dialog>

            <system-dialog :title="assignDialog.title" :width="assignDialog.width" :height="assignDialog.height"
                :visible="assignDialog.visible" @onClose="onAssignClose" @onConfirm="onAssignConfirm">
                <div slot="content">
                    <el-table ref="roleSelection" @selection-change="handleSelectionChange" :height="assignHeight"
                        :data="roleList" border stripe style="width: 100%;margin-bottom: 10px;">
                        <el-table-column type="selection" width="55"></el-table-column>
                        <el-table-column prop="roleName" label="角色名称"></el-table-column>
                        <el-table-column prop="remark" label="描述"></el-table-column>
                    </el-table>
                </div>
            </system-dialog>
        </el-main>
    </el-container>
</template>

<script>

import departmentApi from '@/api/department'
import { getUserList, addUser, updateUser, deleteUser, getRoleList, saveRoleAssign, getUserRole } from '@/api/user'
import SystemDialog from '@/components/system/SystemDialog.vue'
import { getToken } from '@/utils/auth'

export default {
    name: "userList",
    components: {
        SystemDialog
    },
    data() {
        let validatePhone = (rule, value, callback) => {
            if (!value) {
                callback(new Error("请输入手机号码"))
            } else if (!/^1[3456789]\d{9}$/.test(value)) {
                callback(new Error("手机号码格式不正确"))
            } else {
                callback()
            }
        }

        return {
            containerHeight: 0,
            assignHeight: 0,
            deptList: [],
            defaultProps: {
                children: "children",
                label: "departmentName"
            },
            searchModel: {
                username: "",
                realName: "",
                phone: "",
                departmentId: "",
                pageNo: 1,
                pageSize: 10
            },
            tableHeight: 0,
            userList: [],
            pageNo: 1,
            pageSize: 10,
            total: 0,
            departmentId: "",
            user: {
                id: "",
                departmentId: "",
                departmentName: "",
                email: "",
                realName: "",
                phone: "",
                nickName: "",
                password: "",
                username: "",
                gender: "",
                avatar: "",
            },
            userDialog: {
                title: "",
                width: 610,
                height: 410,
                visible: false,
            },
            rules: {
                departmentName: [{ required: true, trigger: 'change', message: '请选择所属部门' }],
                realName: [{ required: true, trigger: 'blur', message: '请填写姓名' }],
                phone: [{ trigger: 'blur', validator: validatePhone }],
                username: [{ required: true, trigger: 'blur', message: '请填写登录名' }],
                password: [{ required: true, trigger: 'blur', message: '请填写登录密码' }],
                gender: [{ required: true, trigger: 'change', message: '请选择性别' }]
            },
            parentDialog: {
                title: "",
                width: 300,
                height: 450,
                visible: false,
            },
            parentList: [],
            uploadHeader: { "token": getToken() },
            roleList: [],
            assignDialog: {
                title: "",
                width: 610,
                height: 410,
                visible: false
            },
            userId: "",
            assignSelection: []
        }
    },
    created() {
        this.getDeptList()
        this.search(this.departmentId)
    },
    mounted() {
        this.$nextTick(() => {
            this.containerHeight = window.innerHeight - 85
            this.tableHeight = window.innerHeight - 220
            this.assignHeight = window.innerHeight - 350
        })
    },
    methods: {
        async getDeptList() {
            let res = await departmentApi.getDepartmentList()
            if (res.success) {
                this.deptList = res.data
                this.$nextTick(() => {
                    const firstNode = document.querySelector(".el-tree-node")
                    firstNode.click()
                })
            }
        },
        handleNodeClick(node) {
            this.departmentId = node.id
            this.search(this.departmentId)
        },
        changeIcon(data) {
            data.open = !data.open
            this.$refs.leftTree.store.nodesMap[data.id].expanded = !data.open
        },
        async search(departmentId, pageNo = 1, pageSize = 10) {
            this.searchModel.pageNo = pageNo
            this.searchModel.pageSize = pageSize
            this.searchModel.departmentId = this.departmentId
            let res = await getUserList(this.searchModel)
            if (res.success) {
                this.userList = res.data.records
                this.total = res.data.total
            }
        },
        resetValue() {
            this.searchModel.username = ''
            this.searchModel.realName = ''
            this.searchModel.phone = ''
            this.search(this.departmentId, this.pageNo, this.pageSize)
        },
        openAddWindow() {
            this.$resetForm("userForm", this.user)
            this.userDialog.title = "新增用户"
            this.userDialog.type = "add"
            this.userDialog.visible = true
        },
        onClose() {
            this.userDialog.visible = false
        },
        onConfirm() {
            this.$refs.userForm.validate(async (valid) => {
                if (valid) {
                    let res = null
                    if (this.user.id === '') {
                        res = await addUser(this.user)
                    } else {
                        res = await updateUser(this.user)
                    }
                    if (res.success) {
                        this.$message.success(res.message)
                        this.search(this.departmentId, this.pageNo, this.pageSize)
                        this.userDialog.visible = false
                    } else {
                        this.$message.error(res.message)
                    }
                }
            })
        },
        async selectDepartment() {
            let res = await departmentApi.getDepartmentList()
            if (res.success) {
                this.parentList = res.data
            }
            this.parentDialog.title = "选择所属部门"
            this.parentDialog.visible = true
        },
        onParentClose() {
            this.parentDialog.visible = false
        },
        onParentConfirm() {
            this.parentDialog.visible = false
        },
        parentClick(node) {
            this.user.departmentName = node.departmentName
            this.user.departmentId = node.id
        },
        changeParentIcon(data) {
            data.open = !data.open
            this.$refs.parentTree.store.nodesMap[data.id].expanded = !data.open
        },
        handleEdit(row) {
            this.$objCopy(row, this.user)
            this.userDialog.title = "修改用户"
            this.userDialog.visible = true
        },
        async handleDelete(row) {
            let confirm = await this.$myconfirm("确认要删除该数据吗?")
            if (confirm) {
                let res = await deleteUser({ id: row.id })
                if (res.success) {
                    this.$message.success(res.message)
                    this.search(this.departmentId, this.pageNo, this.pageSize)
                } else {
                    this.$message.error(res.message)
                }
            }
        },
        async assignRole(row) {
            let res = await getRoleList()
            if (res.success) {
                this.roleList = res.data
                this.userId = row.id

                this.$nextTick(async () => {

                    let res = await getUserRole({ id: row.id })
                    if (res.success) {
                        this.roleList.forEach((item) => {
                            if (res.data.includes(item.id)) {
                                this.$refs.roleSelection.toggleRowSelection(item)
                            }
                        })
                    }
                })
            }
            this.assignDialog.title = "分配角色"
            this.assignDialog.visible = true
        },
        handleSelectionChange(data) {
            this.assignSelection = data.map((item) => item.id)
        },
        onAssignClose() {
            this.assignDialog.visible = false
        },
        async onAssignConfirm() {
            let params = {
                userId: this.userId,
                roleIds: this.assignSelection
            }

            let res = await saveRoleAssign(params)

            if (res.success) {
                this.$message.success(res.message)
                this.assignDialog.visible = false
            } else {
                this.$message.error(res.message)
            }

        },
        handleCurrentChange(pageNo) {
            this.pageNo = pageNo
            this.search(this.departmentId, pageNo, this.pageSize)
        },
        handleSizeChange(pageSize) {
            this.pageSize = pageSize
            this.search(this.departmentId, this.pageNo, pageSize)
        },
        handleAvatarSuccess(res, file) {
            this.user.avatar = res.data
            this.$forceUpdate()
        },
        beforeAvatarUpload(file) {
            const isJPG = file.type === 'image/jpeg'
            const isLt2M = file.size / 1024 / 1024 < 2
            if (!isJPG) {
                this.$message.error('上传头像图片只能是 JPG 格式!')
            }
            if (!isLt2M) {
                this.$message.error('上传头像图片大小不能超过 2MB!')
            }
            return isJPG && isLt2M
        }
    }
}
</script>

<style lang="scss" scoped>
::v-deep .el-tree {
    .el-tree-node {
        position: relative;
        padding-left: 10px;
    }

    .el-tree-node__children {
        padding-left: 20px;
    }

    .el-tree-node :last-child:before {
        height: 40px;
    }

    .el-tree>.el-tree-node:before {
        border-left: none;
    }

    .el-tree>.el-tree-node:after {
        border-top: none;
    }

    .el-tree-node:before,
    .el-tree-node:after {
        content: "";
        left: -4px;
        position: absolute;
        right: auto;
        border-width: 1px;
    }

    .tree :first-child .el-tree-node:before {
        border-left: none;
    }

    .el-tree-node:before {
        border-left: 1px dotted #d9d9d9;
        bottom: 0px;
        height: 100%;
        top: -25px;
        width: 1px;
    }

    .el-tree-node:after {
        border-top: 1px dotted #d9d9d9;
        height: 20px;
        top: 14px;
        width: 24px;
    }

    .el-tree-node__expand-icon.is-leaf {
        width: 8px;
    }

    .el-tree-node__content>.el-tree-node__expand-icon {
        display: none;
    }

    .el-tree-node__content {
        line-height: 30px;
        height: 30px;
        padding-left: 10px !important;
    }
}

::v-deep .el-tree>div {
    &::before {
        display: none;
    }

    &::after {
        display: none;
    }
}

.avatar-uploader {
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
}

.avatar-uploader:hover {
    border-color: #409EFF;
}

.avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 178px;
    height: 178px;
    line-height: 178px;
    text-align: center;
}

.avatar {
    width: 178px;
    height: 178px;
    display: block;
}
</style>